////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copyright (c) 2009 - 2010 RacoonStudios
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this
/// software and associated documentation files (the "Software"), to deal in the Software
/// without restriction, including without limitation the rights to use, copy, modify, merge,
/// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
/// to whom the Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all copies or
/// substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
/// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
/// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
/// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
/// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
/// DEALINGS IN THE SOFTWARE.
////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once
#ifndef weakptr_h__
#define weakptr_h__

#include "core\types.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
/// \class	WeakPtr
///
/// \brief	A weak pointer is nearly just the same as a smrt pointer.
///			The only main difference is that the weak pointer don't take care about
///			reference conting of the object it contains.
///			For this we are using the smart pointer.
///
/// \author	khaos
/// \date	12.12.2009
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
class WeakPtr
{
	public:

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	WeakPtr()
		///
		/// \brief	Default constructor. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		////////////////////////////////////////////////////////////////////////////////////////////////////
		WeakPtr();

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	WeakPtr(T * ptr)
		///
		/// \brief	Constructor. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \param	[in]	ptr	Pointer.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		WeakPtr(T * ptr);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	WeakPtr(const WeakPtr<T> & rhs)
		///
		/// \brief	Constructor. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \param	[in]	rhs	The right hand side object. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		WeakPtr(const WeakPtr<T> & rhs);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	WeakPtr(const SmrtPtr<T> & rhs)
		///
		/// \brief	Copy constructor. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \param	[in]	rhs	The right hand side object. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		WeakPtr(const SmrtPtr<T> & rhs);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	~WeakPtr()
		///
		/// \brief	Finaliser. 
		///
		/// \author	khaos
		/// \date	14.12.2009
		////////////////////////////////////////////////////////////////////////////////////////////////////
		~WeakPtr();




		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	void operator= (T * rhs)
		///
		/// \brief	Copy operator. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \param	[in]	rhs	The pointer.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		void operator = (T * rhs);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	void operator= (const SmrtPtr<T> & rhs)
		///
		/// \brief	Copy operator. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \param	[in]	rhs	Transfers the object of a smart pointer.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		void operator = (const SmrtPtr<T> & rhs);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	void operator= (const WeakPtr<T> & rhs)
		///
		/// \brief	Copy operator. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \param	[in]	rhs	Transfers the object of another weak pointer.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		void operator = (const WeakPtr<T> & rhs);

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	bool operator== (const WeakPtr<T> & rhs) const
		///
		/// \brief	Equality operator. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \param	[in]	rhs	Another weak pointer.
		///
		/// \return	True if the two objects are the same, otherwise false.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		bool operator == (const WeakPtr<T> & rhs) const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	bool operator== (const Smrtptr<T> & rhs) const
		///
		/// \brief	Equality operator. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \param	[in]	rhs	A smart pointer.
		///
		/// \return	True if the two objects are the same, otherwise false.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		bool operator == (const Smrtptr<T> & rhs) const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	bool operator!= (const WeakPtr<T> & rhs) const
		///
		/// \brief	Inequality operator. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \param	[in]	rhs	Another weak pointer.
		///
		/// \return	True if the two objects are inequal, otherwise false.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		bool operator != (const WeakPtr<T> & rhs) const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	bool operator!= (const SmrtPtr<T> & rhs) const
		///
		/// \brief	Inequality operator. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \param	[in]	rhs	A smart pointer.
		///
		/// \return	True if the two objects are inequal, otherwise false.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		bool operator != (const SmrtPtr<T> & rhs) const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	T * operator-> () const
		///
		/// \brief	-> operator. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \return	Returns pointer.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		T * operator -> () const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	T & operator* () const
		///
		/// \brief	Dereference operator. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		///
		/// \return	The result of the operation. 
		////////////////////////////////////////////////////////////////////////////////////////////////////
		T & operator * () const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	operatorT * () const
		///
		/// \brief	Pointer cast operator. 
		///
		/// \author	khaos
		/// \date	12.12.2009
		////////////////////////////////////////////////////////////////////////////////////////////////////
		operator T * () const;




		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	bool isvalid() const
		///
		/// \brief	Returns if the weak pointer is valid.
		///
		/// \author	khaos
		/// \date	14.12.2009
		///
		/// \return	True if weak pointer is valid, otherwise false.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		bool isvalid() const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// \fn	T * get() const
		///
		/// \brief	Returns the object.
		///
		/// \author	khaos
		/// \date	14.12.2009
		///
		/// \return	The pointer of the weak pointer.
		////////////////////////////////////////////////////////////////////////////////////////////////////
		T * get() const;

	protected:

		T * m_ptr;

	private:

};





///
template<class T>
inline WeakPtr<T>::WeakPtr():
m_ptr(NULL)
{

}


///
template<class T>
inline WeakPtr<T>::WeakPtr(T *ptr):
m_ptr(ptr)
{

}


///
template<class T>
inline WeakPtr<T>::WeakPtr(const WeakPtr<T> &rhs):
m_ptr(rhs.m_ptr)
{

}


///
template<class T>
inline WeakPtr<T>::WeakPtr(const SmrtPtr<T> &rhs):
m_ptr(rhs.get())
{

}


///
template<class T>
inline WeakPtr<T>::~WeakPtr()
{
	this->m_ptr = 0;
}





///
template<class T>
inline void WeakPtr<T>::operator =(const WeakPtr<T> &rhs)
{
	this->m_ptr = rhs.m_ptr;
}


///
template<class T>
inline void WeakPtr<T>::operator =(const SmrtPtr<T> &rhs)
{
	this->m_ptr = rhs.get();
}


///
template<class T>
inline void WeakPtr<T>::operator =(T *rhs)
{
	this->m_ptr = rhs;
}


///
template<class T>
inline bool WeakPtr<T>::operator ==(const WeakPtr<T> &rhs) const
{
	return (this->m_ptr == rhs.m_ptr);
}


///
template<class T>
inline bool WeakPtr<T>::operator ==(const Smrtptr<T> &rhs) const
{
	return (this->m_ptr == rhs.get());
}


///
template<class T>
inline bool WeakPtr<T>::operator !=(const WeakPtr<T> &rhs) const
{
	return (this->m_ptr != rhs.m_ptr);
}


///
template<class T>
inline bool WeapPtr<T>::operator !=(const SmrtPtr<T> & rhs) const
{
	return (this->m_ptr != rhs.get());
}


///
template<class T>
inline T * WeakPtr<T>::operator ->() const
{
	return this->m_ptr;
}


///
template<class T>
inline WeakPtr<T>::operator T *() const
{
	return this->m_ptr;
}


///
template<class T>
inline T & WeakPtr<T>::operator *() const
{
	return &(this->m_ptr);
}





///
template<class T>
inline T * WeakPtr<T>::get() const
{
	return this->m_ptr;
}


///
template<class T>
inline bool WeakPtr<T>::isvalid() const
{
	return (this->m_ptr != NULL);
}

#endif // weakptr_h__